﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.DirectoryServices;
using System.Security.AccessControl;

namespace MailboxRightsLookup
{
    // MailboxPermission cannot be a struct because it would be stored by value
    // in the intermediate resultDict (see ReverseSearcher.IndexMailboxPermissions)
    // and it would cause more trouble than benefit since it's not immutable
    // The way SendAs permissions are gathered, reusing MailboxPermissions that might
    // have been create with the FullAccess permission, make them necessarily
    // mutable and better off implementing MailboxPermission to be a class
    class MailboxPermission
    {
        static readonly Guid SendAsObjectType = new Guid("ab721a54-1e2f-11d0-9819-00aa0040529b");

        [Flags]
        enum PermissionType : short
        {
            None = 0x0,
            FullAccess = 0x1,
            SendAs = 0x2
        }

        // Depending on the scale of the Exchange deployment, the application will typically
        // allocate various thousands of MailboxPermission objects. Therefore it is crucial to
        // to keep this class very lightweight. _path string should not be a concern due to
        // .net's string interning (there will only be one different path per domain).
        // _permissions will likely use 4-bytes due to byte alignment
        Guid _mailboxGuid;
        string _path;
        PermissionType _permissions;

        public Guid mailboxGuid { get { return _mailboxGuid; } }
        public string path { get { return _path; } }
        public bool fullAccess { get { return _permissions.HasFlag(PermissionType.FullAccess); } }
        public bool sendAs { get { return _permissions.HasFlag(PermissionType.SendAs); } }

        public MailboxPermission(Guid mailboxGuid, string path)
        {
            _mailboxGuid = mailboxGuid;
            _path = path;
            _permissions = PermissionType.None;
        }

        public bool HasFullAccessPermission(ActiveDirectoryAccessRule rule)
        {
            if (rule.AccessControlType.HasFlag(AccessControlType.Allow))
                if (rule.ActiveDirectoryRights.HasFlag(ActiveDirectoryRights.CreateChild))
                {
                    _permissions |= PermissionType.FullAccess;
                    return true;
                }
            return false;
        }

        public bool HasSendAsPermission(ObjectAccessRule rule)
        {
            if (rule.AccessControlType.HasFlag(AccessControlType.Allow))
                if (rule.ObjectType == SendAsObjectType)
                {
                    _permissions |= PermissionType.SendAs;
                    return true;
                }
            return false;
        }

    }
}
